package com.aier.user.action.pay.alipay;

import java.io.PrintWriter;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.Security;
import java.util.Map;

import javax.annotation.Resource;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import com.aier.user.action.UserBaseAction;
import com.aier.user.action.pay.alipay.util.StringUtil;
import com.aier.user.entity.userapp.Bill;
import com.aier.user.entity.userapp.Commidity;
import com.aier.user.service.IUserBuyService;

@Scope("prototype")
@Component("userAlipayAction")
public class UserAlipayAction extends UserBaseAction {

    private static final long serialVersionUID = 1L;
    
    //签名成功
    public static final int RESULT_CHECK_SIGN_SUCCEED = 1;
    //签名失败
    public static final int RESULT_CHECK_SIGN_FAILED =0;
    
    static {
        Security.addProvider(new BouncyCastleProvider());
    }
    
    @Resource(name = "userBuyService")
    private IUserBuyService userBuyService;

    private int s;
    private String strReString;     //签名结果
    // 订单id
    private Long bill_id;
    
    private String sign;             //签名
    private String notify_data;        //通知业务数据
//    private String trade_status;    //交易状态  TRADE_FINISHED：表示交易成功完成  WAIT_BUYER_PAY：表示等待付款
//    private String total_fee;        //交易金额    大于 0 的数字，精确到小数点后两位
//    private String subject;            //商品名称
//    private String out_trade_no;    //商户网站唯一订单号
//    private String notify_reg_time;    //通知时间
//    private String trade_no;        //支付宝交易号
    
    @Override
    public String execute() {
        return SUCCESS;
    }

    /**
     * 安全支付支付完成商户同步处理程序
     * 对支付宝返回订单信息验签名
     * @return
     */
    public String RSACallBack(){
        
        s = RESULT_CHECK_SIGN_FAILED;
        //使用支付宝公钥验签名
        try {
            //获得待签名数据和签名值
            String sign = URLDecoder.decode(request.getParameter("sign"),"utf-8");
            String content = URLDecoder.decode(request.getParameter("content"),"utf-8");
            if(RSASignature.doCheck(content, sign, PartnerConfig.RSA_ALIPAY_PUBLIC)){
                s = RESULT_CHECK_SIGN_SUCCEED;
            }
            
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("验签名失败");
        }
        return SUCCESS;
    }
    
    /**
     * 接收通知并处理 异步通知
     * @return
     */
    public String RSANotifyReceiver(){
        System.out.println("接收到通知!");
        //获得通知参数
        Map map = request.getParameterMap();
        System.out.println("notify_data="+notify_data+"&sign="+sign);
        //获得通知签名
//        String sign = (String) ((Object[]) map.get("sign"))[0];
        //获得待验签名的数据
        String verifyData = findVerifyData(map);
        boolean verified = false;
        //使用支付宝公钥验签名
        try {
            verified = RSASignature.doCheck(verifyData, sign, PartnerConfig.RSA_ALIPAY_PUBLIC);
            PrintWriter out = response.getWriter();
            //验证签名通过
            if (verified) {
                //根据交易状态处理业务逻辑
                //当交易状态成功，处理业务逻辑成功。回写success
                String trade_status = notify_data.split("<trade_status>")[1].split("<")[0];
                String out_trade_no =  notify_data.split("<out_trade_no>")[1].split("<")[0];
                if("TRADE_FINISHED".equals(trade_status)){
                    userBuyService.updateBuyServiceSuccess(Long.valueOf(out_trade_no));
                }
                
                out.print("success");
                out.flush();
                out.close();
            } else {
                System.out.println("接收支付宝系统通知验证签名失败，请检查！");
                out.print("fail");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return SUCCESS;
    }

    
    /**
     * 安全支付服务器端处理程序
     * 
     * 1.将业务参数：合作商户ID、 外部交易号、商品名称、商品的具体描述、商品总价、卖家帐户、notify_url这些参数按照固定顺序签名
     * 2.将签名结果返回客户端
     * @return
     * @throws IOException 
     */
    public String RSATrade(){
//        System.out.println("request in");
        Bill bill = userBuyService.searchBillById(bill_id);
        
        //检查商户PartnerConfig.java文件的配置参数
        if(!checkInfo()){
            s = 0;
            return SUCCESS;
        }
        String signData=findSignDate(bill);
        String sign = sign(signData,PartnerConfig.RSA_PRIVATE);
        //返回待签名数据和签名数据
//        strReString = "<result><is_success>T</is_success><content>"+signData+"</content><sign>"+sign+"</sign></result>";
        strReString = signData + "&sign=" + "\"" + URLEncoder.encode(sign) + "\"" + "&sign_type=\"RSA\"";
        System.out.println(strReString);
        s = 1;
        return SUCCESS;
    }
    
    
    // 获得验签名的数据
    private String findVerifyData(Map map) {
        String notify_data = (String) ((Object[]) map.get("notify_data"))[0];
        return "notify_data="+notify_data;
    }
    
    // 检查商户PartnerConfig.java文件的配置参数
    private boolean checkInfo() {
        String partner = PartnerConfig.PARTNER;
        String seller = PartnerConfig.SELLER;
        //如果合作商户ID为空或者账号ID为空返回false
        if (StringUtil.isBlank(partner) || StringUtil.isBlank(seller)) {
            return false;
        }
        return true;
    }
    
    // 准备待签名的数据 @param request @throws UnsupportedEncodingException
    private String findSignDate(Bill bill) {    
        Commidity commidity = userBuyService.searchCommidity(bill.getCid());
        //合作商户ID
        String partner = PartnerConfig.PARTNER;
        //卖家帐号
        String seller = PartnerConfig.SELLER;
        // 外部交易号 这里取当前时间，商户可根据自己的情况修改此参数，但保证唯一性
        String outTradeNo = bill.getBid() + "";
        // 商品名称
        String subject = commidity.getCname().trim();
        // 商品具体描述
        String body = commidity.getDescription().trim();
        // 商品总价
//        String totalFee = bill.getMoney() + ".0";
        String totalFee = "0.01";
        // 接收支付宝发送的通知的url 商户可根据自己的情况修改此参数
        String notify_url = aier_url+"userjs/userAlipay_RSANotifyReceiver.shtml";
        //组装待签名数据
        String signData = "partner=" + "\"" + partner + "\"";
        signData += "&";
        signData += "seller=" + "\"" + seller + "\"";
        signData += "&";
        signData += "out_trade_no=" + "\"" + outTradeNo + "\"";
        signData += "&";
        signData += "subject=" + "\"" + subject+ "\"";
        signData += "&";
        signData += "body=" + "\"" + body + "\"";
        signData += "&";
        signData += "total_fee=" + "\""+ totalFee + "\"";
        signData += "&";
        signData += "notify_url=" + "\""+notify_url+ "\"";
        return signData;
    }
    
    // 对参数进行签名 @param signData 待签名数据，key rsa商户私钥
    private String sign(String signData,String key) {
        System.out.println("signData:"+signData);
        String sign = "";
        try {
            sign = RSASignature.sign(signData, key);
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        return sign;
    }
    
    
    
    public void setUserBuyService(IUserBuyService userBuyService) {
        this.userBuyService = userBuyService;
    }

    public int getS() {
        return s;
    }

    public String getStrReString() {
        return strReString;
    }

    public void setBill_id(Long bill_id) {
        this.bill_id = bill_id;
    }

    public void setSign(String sign) {
        this.sign = sign;
    }

    public String getSign() {
        return sign;
    }

    public void setNotify_data(String notify_data) {
        this.notify_data = notify_data;
    }

}
